#include "stdafx.h"
#include "TerrianMesh.h"
#include "MeshSort.h"
#include <osgDB/ReaderWriter>
#include <osgDB/ReadFile>

void TerrianMesh::SaveData(CFileSaveData& fp)
{
	m_pSort->Save(fp);
	fp.GetStream().flush();
	MeshGroup::SaveData(fp);
	fp.GetStream().flush();
}
void TerrianMesh::LoadData(CFileLoadData& fp)
{
	m_pSort = shared_ptr<MeshSort>(new MeshSort());
	m_pSort->Load(fp);
	MeshGroup::LoadData(fp);
}
void TerrianMesh::LoadFromDimine(string strFileName, bool isNeedCalSort, bool isNotCheck)
{
	MeshGroup::LoadFromDimine(strFileName, isNotCheck);
	if (isNeedCalSort)
	{
		m_pSort = shared_ptr<MeshSort>(new MeshSort(m_vMesh));
	}

}

void TerrianMesh::LoadFromOff(string strFoldPath, int iFrom, int iNum, bool isNeedCalSort)
{
	MeshGroup::LoadFromOff(strFoldPath, iFrom, iNum);
	if (isNeedCalSort)
	{
		m_pSort = shared_ptr<MeshSort>(new MeshSort(m_vMesh));
	}
}

void TerrianMesh::LoadFromOsg(string strTerrainName)
{
	osg::ref_ptr<osg::Node> pTerrainNode = osgDB::readNodeFile(strTerrainName);
	MeshData meshHandle;
	m_vMesh = meshHandle.CreateGroup(pTerrainNode);

	/*MeshData mesh = m_vMesh[2];
	m_vMesh.clear();
	m_vMesh.push_back(mesh);*/
	m_pSort = shared_ptr<MeshSort>(new MeshSort(m_vMesh));
}

TerrianMesh::TerrianMesh():MeshGroup("Terrain")
{

}

MeshData TerrianMesh::CalSelfInterMesh(bool isNeedRemoveFace)
{
	int iFrom = 0;
	vector<Point_3> vPnt;
	vector<unsigned int> vTri;
	for (MeshData& meshTerrain : m_vMesh)
	{
		meshTerrain.RemoveDegenerateFaces();
		std::vector<pair<mesh_face_descriptor, mesh_face_descriptor>> vIntersected = meshTerrain.GetSelfIntersect();
		if (!vIntersected.empty())
		{
			vector<Point_3> vPntTemp;
			vector<unsigned int> vTriTemp;
			meshTerrain.ToData(vPntTemp, vTriTemp);
			std::vector <mesh_face_descriptor>vFace;
			for (auto paFace : vIntersected)
			{
				vFace.push_back(paFace.first);
				vFace.push_back(paFace.second);
			}
			vector<suFaceInx> vFaceInx = meshTerrain.GetFaceInx(vFace);
			map<int, int> vReInx;
			int inx = 0;
			for (suFaceInx faceInx : vFaceInx)
			{
				for (int i = 0; i < 3; ++i)
				{
					int inxPnt = faceInx.m_inx[i];
					if (vReInx.find(inxPnt) == vReInx.end())
					{
						vReInx[inxPnt] = inx + iFrom;
						vPnt.push_back(vPntTemp[inxPnt]);
						++inx;
					}
				}
			}
			
			for (suFaceInx faceInx : vFaceInx)
			{
				for (int i = 0; i < 3; ++i)
				{
					int inxPnt = faceInx.m_inx[i];
					vTri.push_back(vReInx[inxPnt]);
				}
			}
			iFrom += vReInx.size();
			if (isNeedRemoveFace)
			{
				meshTerrain.RemoveFace(vFace);
			}
		}
	
	}
	if (vTri.empty())
	{
		return MeshData();
	}
	return MeshData(vPnt, vTri);
}

int TerrianMesh::GetHeight(double& z, double x, double y) const
{
	return m_pSort->GetHeight(z, x, y);
}

